package com.huawei.lynnbit.tool.cocos.processor.preset;

import com.google.common.collect.Lists;
import com.huawei.lynnbit.tool.cocos.config.game.CocosVersion;
import com.huawei.lynnbit.tool.cocos.config.game.GameConfig;
import com.huawei.lynnbit.tool.cocos.config.game.task.ReplaceFileTask;
import com.huawei.lynnbit.tool.cocos.config.game.task.ReplaceStringTask;
import com.huawei.lynnbit.tool.cocos.config.game.task.Stage;
import com.huawei.lynnbit.tool.cocos.config.game.task.Task;
import com.huawei.lynnbit.tool.cocos.processor.CompositeProcessor;
import com.huawei.lynnbit.tool.cocos.processor.Processor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Slf4j
public class AppProcessor implements Processor {
    private static final String MODULE_JSON5 = "\\entry\\src\\main\\module.json5";
    private static final String APP_SCOPE_STRING_JSON = "\\AppScope\\resources\\base\\element\\string.json";
    private static final String ENTRY_STRING_JSON = "\\entry\\src\\main\\resources\\base\\element\\string.json";
    private static final String ENTRY_COLOR_JSON = "\\entry\\src\\main\\resources\\base\\element\\color.json";
    private static final String APP_JSON5 = "\\AppScope\\app.json5";
    private static final String APP_SCOPE_ICON_PNG = "\\AppScope\\resources\\base\\media\\app_icon.png";
    private static final String ENTRY_ICON_PNG = "\\entry\\src\\main\\resources\\base\\media\\icon.png";
    private static final String ASSETS_DIR = "\\entry\\src\\main\\resources\\rawfile\\assets";
    private static final String JSB_ADAPTER_DIR = "\\entry\\src\\main\\resources\\rawfile\\jsb-adapter";
    private static final String SRC_DIR = "\\entry\\src\\main\\resources\\rawfile\\src";
    private static final String MAIN_JS_FILE = "\\entry\\src\\main\\resources\\rawfile\\main.js";
    private static final String ASSETS_DIR_IN_RAW_FILE = "\\assets";
    private static final String JSB_ADAPTER_DIR_IN_RAW_FILE = "\\jsb-adapter";
    private static final String SRC_DIR_IN_RAW_FILE = "\\src";
    private static final String MAIN_JS_FILE_IN_RAW_FILE = "\\main.js";
    private static final String RESOURCES_DIR = "\\entry\\src\\main\\resources\\rawfile\\Resources";
    private static final String RAW_FILE_DIR = "\\entry\\src\\main\\resources\\rawfile";
    private static final String LOADING_BG_PNG = "\\entry\\src\\main\\resources\\base\\media\\loading_bg.png";
    private static final String LOADING_LOGO_PNG = "\\entry\\src\\main\\resources\\base\\media\\loading_logo.png";
    private static final String AGE_RATE_BG_FILE = "\\entry\\src\\main\\resources\\base\\media\\age_rate.png";

    private GameConfig gameConfig;

    public AppProcessor(GameConfig config) {
        this.gameConfig = config;
    }

    @Override
    public void process() throws Exception {
        log.info("start to config appinfo in harmonyos next project >>>>>>>>>>>>>>>>>>>>>>>>");
        List<Task> taskList = new ArrayList<>();
        taskList.addAll(getExportProcessTask(gameConfig));
        taskList.addAll(getAppProcessTask(gameConfig));
        Processor compositeProcessor = new CompositeProcessor(taskList, gameConfig);
        compositeProcessor.process();
    }

    private Collection<? extends Task> getAppProcessTask(GameConfig gameConfig) {
//        CopySnippetTask appIdCopyTask = CopySnippetTask.builder()
//                .stage(Stage.ASSEMBLE_APP)
//                .type(Task.TYPE_COPY_SNIPPET)
//                .destPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
//                .destPattern("\"?pages\"?\s*:\s*\"[$:a-zA-Z_]*\",(\n|\r\n)")
//                .snippet("    \"metadata\": [\n" +
//                        "      {\n" +
//                        "        \"name\": \"client_id\",\n" +
//                        "        \"value\": \"" + gameConfig.getAppInfo().getClientId() + "\"\n" +
//                        "      },\n" +
//                        "      {\n" +
//                        "        \"name\": \"app_id\",\n" +
//                        "        \"value\": \"" + gameConfig.getAppInfo().getAppId() + "\"\n" +
//                        "      }\n" +
//                        "    ],\n")
//                .build();

        ReplaceStringTask appIdReplaceTaskInModuleJson5 = ReplaceStringTask.builder()
                .stage(Stage.ASSEMBLE_APP)
                .type(Task.TYPE_REPLACE_STRING)
                .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                .srcPattern("\"name\"\s*:\s*\"app_id\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                .destString("\"name\": \"app_id\",\n" +
                        "        \"value\": \"" + gameConfig.getAppInfo().getAppId() + "\"")
                .build();

        ReplaceStringTask clientIdReplaceTaskInModuleJson5 = ReplaceStringTask.builder()
                .stage(Stage.ASSEMBLE_APP)
                .type(Task.TYPE_REPLACE_STRING)
                .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                .srcPattern("\"name\"\s*:\s*\"client_id\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                .destString("\"name\": \"client_id\",\n" +
                        "        \"value\": \"" + gameConfig.getAppInfo().getClientId() + "\"")
                .build();

        List<Task> ret = Lists.newArrayList(appIdReplaceTaskInModuleJson5, clientIdReplaceTaskInModuleJson5);

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getAppName())) {
            ReplaceStringTask appNameReplaceTaskInAppScope = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + APP_SCOPE_STRING_JSON)
                    .srcPattern("\"name\"\s*:\s*\"app_name\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"app_name\",\n" +
                            "      \"value\": \"" + gameConfig.getAppInfo().getAppName() + "\"")
                    .build();


            ReplaceStringTask appNameReplaceTaskInEntry = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + ENTRY_STRING_JSON)
                    .srcPattern("\"name\"\s*:\s*\"MainAbility_label\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"MainAbility_label\",\n" +
                            "      \"value\": \"" + gameConfig.getAppInfo().getAppName() + "\"")
                    .build();

            ret.add(appNameReplaceTaskInAppScope);
            ret.add(appNameReplaceTaskInEntry);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getPackageName())) {
            ReplaceStringTask packageNameReplaceTask = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + APP_JSON5)
                    .srcPattern("\"?bundleName\"?\s*:\s*\"[a-zA-Z0-9._]*\"")
                    .destString("\"bundleName\": \"" + gameConfig.getAppInfo().getPackageName() + "\"")
                    .build();

            ret.add(packageNameReplaceTask);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getVersion())) {
            ReplaceStringTask versionReplaceTask = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + APP_JSON5)
                    .srcPattern("\"?versionName\"?\s*:\s*\"[a-zA-Z0-9._]*\"")
                    .destString("\"versionName\": \"" + gameConfig.getAppInfo().getVersion() + "\"")
                    .build();

            ret.add(versionReplaceTask);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getIconPath())) {
            ReplaceFileTask iconReplaceTaskInAppScope = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .destPath(gameConfig.getDevEcoProjectPath() + APP_SCOPE_ICON_PNG)
                    .srcPath(gameConfig.getAppInfo().getIconPath())
                    .build();

            ReplaceFileTask iconReplaceTaskInEntry = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .destPath(gameConfig.getDevEcoProjectPath() + ENTRY_ICON_PNG)
                    .srcPath(gameConfig.getAppInfo().getIconPath())
                    .build();

            ret.add(iconReplaceTaskInAppScope);
            ret.add(iconReplaceTaskInEntry);
        }


        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getRewardAdId())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"ad_id_reward\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"ad_id_reward\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getRewardAdId() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getInterstitialAdId())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"ad_id_interstitial\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"ad_id_interstitial\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getInterstitialAdId() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getSplashAdId())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"ad_id_splash\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"ad_id_splash\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getSplashAdId() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getBannerAdId())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"ad_id_banner\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"ad_id_banner\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getBannerAdId() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getUserAgreementUrl())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"user_agreement_url\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"user_agreement_url\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getUserAgreementUrl() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getPrivacyUrl())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"privacy_url\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"privacy_url\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getPrivacyUrl() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getPrivacyCompany())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"privacy_company\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"privacy_company\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getPrivacyCompany() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getPrivacyEmail())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                    .srcPattern("\"name\"\s*:\s*\"privacy_email\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"privacy_email\",\n" +
                            "        \"value\": \"" + gameConfig.getAppInfo().getPrivacyEmail() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getCopyrightOwner())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + ENTRY_STRING_JSON)
                    .srcPattern("\"name\"\s*:\s*\"copyright_owner\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"copyright_owner\",\n" +
                            "      \"value\": \"" + gameConfig.getAppInfo().getCopyrightOwner() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getSoftCopyrightRegistrationNumber())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + ENTRY_STRING_JSON)
                    .srcPattern("\"name\"\s*:\s*\"softCopyright_registration_number\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"softCopyright_registration_number\",\n" +
                            "      \"value\": \"" + gameConfig.getAppInfo().getSoftCopyrightRegistrationNumber() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getLoadingBg())) {
            ReplaceFileTask tmp = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(gameConfig.getAppInfo().getLoadingBg())
                    .destPath(gameConfig.getDevEcoProjectPath() + LOADING_BG_PNG)
                    .build();
            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getLoadingLogo())) {
            ReplaceFileTask tmp = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(gameConfig.getAppInfo().getLoadingLogo())
                    .destPath(gameConfig.getDevEcoProjectPath() + LOADING_LOGO_PNG)
                    .build();
            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getAgeRateBg())) {
            ReplaceFileTask tmp = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(gameConfig.getAppInfo().getAgeRateBg())
                    .destPath(gameConfig.getDevEcoProjectPath() + AGE_RATE_BG_FILE)
                    .build();
            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getAgeRateText())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + ENTRY_STRING_JSON)
                    .srcPattern("\"name\"\s*:\s*\"age_rate\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"age_rate\",\n" +
                            "      \"value\": \"" + gameConfig.getAppInfo().getAgeRateText() + "\"")
                    .build();

            ret.add(tmp);
        }

        if (StringUtils.isNotBlank(gameConfig.getAppInfo().getLoadingFontColor())) {
            ReplaceStringTask tmp = ReplaceStringTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_STRING)
                    .srcPath(gameConfig.getDevEcoProjectPath() + ENTRY_COLOR_JSON)
                    .srcPattern("\"name\"\s*:\s*\"loading_font\",(\n|\r\n)\s*\"value\"\s*:\s*\".*\"")
                    .destString("\"name\": \"loading_font\",\n" +
                            "      \"value\": \"" + gameConfig.getAppInfo().getLoadingFontColor() + "\"")
                    .build();

            ret.add(tmp);
        }
        return ret;
    }

    private Collection<? extends Task> getExportProcessTask(GameConfig gameConfig) {
        List<Task> ret = new ArrayList<>();
        ReplaceStringTask replaceOrientationTask = ReplaceStringTask.builder()
                .stage(Stage.ASSEMBLE_APP)
                .type(Task.TYPE_REPLACE_STRING)
                .srcPath(gameConfig.getDevEcoProjectPath() + MODULE_JSON5)
                .srcPattern("\"?orientation\"?\s*:\s*\"[a-z_]*\"")
                .destString("\"orientation\": \"" + gameConfig.getExportInfo().getDestOrientation() + "\"")
                .build();
        ret.add(replaceOrientationTask);

        if (CocosVersion.COCOS2.equals(gameConfig.getCocosVersion())) {
            ReplaceFileTask replaceAssetsTask = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(StringUtils.isBlank(gameConfig.getRawFilePath()) ? gameConfig.getBuildPath() + ASSETS_DIR : gameConfig.getRawFilePath() + ASSETS_DIR_IN_RAW_FILE)
                    .destPath(gameConfig.getDevEcoProjectPath() + ASSETS_DIR)
                    .build();

            ReplaceFileTask replaceJsbAdapterTask = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(StringUtils.isBlank(gameConfig.getRawFilePath()) ? gameConfig.getBuildPath() + JSB_ADAPTER_DIR : gameConfig.getRawFilePath() + JSB_ADAPTER_DIR_IN_RAW_FILE)
                    .destPath(gameConfig.getDevEcoProjectPath() + JSB_ADAPTER_DIR)
                    .build();

            ReplaceFileTask replaceSrcTask = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(StringUtils.isBlank(gameConfig.getRawFilePath()) ? gameConfig.getBuildPath() + SRC_DIR : gameConfig.getRawFilePath() + SRC_DIR_IN_RAW_FILE)
                    .destPath(gameConfig.getDevEcoProjectPath() + SRC_DIR)
                    .build();

            ReplaceFileTask replaceMainJsTask = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(StringUtils.isBlank(gameConfig.getRawFilePath()) ? gameConfig.getBuildPath() + MAIN_JS_FILE : gameConfig.getRawFilePath() + MAIN_JS_FILE_IN_RAW_FILE)
                    .destPath(gameConfig.getDevEcoProjectPath() + MAIN_JS_FILE)
                    .build();
            ret.add(replaceAssetsTask);
            ret.add(replaceJsbAdapterTask);
            ret.add(replaceSrcTask);
            ret.add(replaceMainJsTask);
        } else {
            ReplaceFileTask replaceResourcesTask = ReplaceFileTask.builder()
                    .stage(Stage.ASSEMBLE_APP)
                    .type(Task.TYPE_REPLACE_FILE)
                    .srcPath(gameConfig.getBuildPath() + RESOURCES_DIR)
                    .destPath(gameConfig.getDevEcoProjectPath() + RESOURCES_DIR)
                    .build();
            ret.add(replaceResourcesTask);
        }

        return ret;
    }
}
